#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/radix-tree.h>
#include <linux/slab.h>
#include <linux/uaccess.h>

#define PAGE_SIZE 4096
#define MAX_PAGES 1024

static RADIX_TREE(file_buffer, GFP_KERNEL);

static int Mwrite(const char *fn, loff_t offset, const char *buff, size_t size)
{
    struct file *file;
    loff_t pos = offset;
    ssize_t written;
    int ret = 0;

    printk(KERN_INFO "Writing to file: %s, Offset: %lld, Size: %zu\n", fn, offset, size);

    file = filp_open(fn, O_WRONLY | O_CREAT, 0644);
    if (IS_ERR(file)) {
        printk(KERN_ERR "Failed to open file: %s\n", fn);
        ret = PTR_ERR(file);
        goto out;
    }

    written = kernel_write(file, buff, size, &pos);
    if (written < 0) {
        printk(KERN_ERR "Failed to write to file: %s\n", fn);
        ret = written;
    }

    filp_close(file, NULL);

out:
    return ret;
}

static int Mread(const char *fn, loff_t offset, char *buff, size_t size)
{
    struct file *file;
    loff_t pos = offset;
    ssize_t read;
    int ret = 0;

    printk(KERN_INFO "Reading from file: %s, Offset: %lld, Size: %zu\n", fn, offset, size);

    file = filp_open(fn, O_RDONLY, 0);
    if (IS_ERR(file)) {
        printk(KERN_ERR "Failed to open file: %s\n", fn);
        ret = PTR_ERR(file);
        goto out;
    }

    read = kernel_read(file, buff, size, &pos);
    if (read < 0) {
        printk(KERN_ERR "Failed to read from file: %s\n", fn);
        ret = read;
    }

    filp_close(file, NULL);

out:
    return ret;
}

static int __init radix_tree_module_init(void)
{
    printk(KERN_INFO "Radix tree module loaded.\n");
    return 0;
}

static void __exit radix_tree_module_exit(void)
{
    printk(KERN_INFO "Radix tree module unloaded.\n");
}

module_init(radix_tree_module_init);
module_exit(radix_tree_module_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Radix tree based file buffer");
